<?php
/**
 * Class UserLogic
 * @package app\common\logic
 */

namespace app\common\logic;
use app\common\help\ContractHelp;
use think\Log;

/**
 * 客户相关逻辑
 *
 * @package app\common\logic
 */
class Contract extends Base
{
    private $contract_type_model;
    private $customer_model;
    private $contract_model;
    private $contract_customer_view_model;

    public function __construct($data = [])
    {
        parent::__construct($data);
        $this->contract_type_model = model('ContractType');
        $this->customer_model = model('Customer');
        $this->contract_model = model('Contract');
        $this->contract_customer_view_model = model('ContractCustomerView');
    }

    /**
     * 提交一个合同信息
     * @param array $data
     * @param array $user_info
     * @param int $id
     * @return mixed
     */
    public function submitContract(array $data, array $user_info, $id = 0)
    {
        if (empty($data)) {
            exception('缺少合同信息！');
        }

        $data = array_map(function ($v) {
            return addslashes(htmlspecialchars(trim($v)));
        }, $data);

        if (empty($user_info)) {
            exception('无法获取登陆人员信息，建议尝试重新登录！');
        }

        //必填字段验证
        if (empty($data['customer_id'])) {
            exception('请先选择客户！');
        } else {
            //检查客户是否存在
            $customer_info = $this->customer_model->getInfo(['id' => $data['customer_id']], 'id');
            if (!$customer_info) {
                exception('指定客户不存在或已被删除，请检查！');
            }
        }

        //检查业务类型参数是否合法
        $type_info = model('ContractType')->getInfo(['id' => $data['type']], true, true);
        if (empty($type_info)) {
            exception('抱歉，您选择的业务类型（子类）不存在或已被删除，请检查');
        }
        if ($type_info['parent_id'] != $data['class']) {
            exception('抱歉，您选择的业务类型父类和子类不匹配，请重新选择！');
        }

        if ($id > 0) {
            $old_info = $this->contract_model->getInfo(['id' => $id], 'id');
            if (empty($old_info)) {
                exception('该合同信息不存在或已被删除，请检查！');
            }

            $res = $this->contract_model->saveDate($id, $data);
            return $res === false ? false : true;
        } else {
            //生成合同编号
            $contract_number_info    = $this->getContractNumber($data['sign_company_code'], $data['year']);

            $data['contract_number'] = $contract_number_info['contract_number'];
            $data['serial_number']   = $contract_number_info['serial_number'];

            //录入相关信息
            $data['add_uid'] = $user_info['id'];
            $data['is_delete'] = 0;
            $data['create_time'] = NOW_TIME;
            $res = $this->contract_model->addData($data);
            if (!$res) {
                return false;
            }

            //添加成功后，标记：被占用合同号的合同 为被占用状态
            if ($contract_number_info['be_discard_contract_id'] > 0) {
                $edit_res = $this->contract_model->saveDate($contract_number_info['be_discard_contract_id'], [
                    'be_used_number' => 1,
                ]);
                if ($edit_res === false) {
                    return false;
                }
            }

            return true;
        }
    }

    /**
     * 生成合同编号规则：“LBH-年份”+序号  年份暂时为：2位
     *
     * 规则：检查同年份的合同中，有没有作废且合同号未被占用的合同，如果有，直接使用其序号，如果没有，则使用最新的
     *
     * @param string $prefix 前缀
     * @param int $year 合同年份(四位)
     * @return string
     */
    public function getContractNumber($prefix, $year)
    {
        if (empty($prefix || empty($year))) {
            exception('缺少必要的参数！');
        }
        $discard_contract_info = $this->contract_model->getbeDiscardContractNumber($year, $prefix);
        if (!empty($discard_contract_info)) {
            return [
                'serial_number'             => $discard_contract_info['serial_number'],
                'contract_number'           => $discard_contract_info['contract_number'],
                'be_discard_contract_id'    => $discard_contract_info['id'],
            ];
        } else {
            $last_number = $this->contract_model->getLastContractNumber($year, $prefix);
            //TODO 后面改造成配置方式
            $number = $last_number + 1;
            $year = substr($year, -2);//
            $contract_number = $prefix . '-' . $year . sprintf("%04d", $number);
            return [
                'serial_number'             => $number,
                'contract_number'           => $contract_number,
                'be_discard_contract_id'    => 0,
            ];
        }
    }

    /**
     * 获取客户列表
     * @param array $where
     * @param array $user_info
     * @param int $limit
     * @param bool $need_address_deta 是否需要地址详细信息
     * @return array
     */
    public function getList(array $where, array $user_info, $limit = 20, $need_address_deta = false)
    {
        $list = $this->contract_customer_view_model->getList($where, $limit);

        if ($need_address_deta) {
            $list_copy = $list->toArray();

            $region_arr = [];
            if ($list_copy['data']) {
                $region_id = array_merge(array_column($list_copy['data'], 'province_id'), array_column($list_copy['data'], 'city_id'), array_column($list_copy['data'], 'district_id'));
                $region_id = array_filter(array_unique($region_id));
                $region_id = array_map(function ($v){
                    return (int)$v;
                }, $region_id);

                if (!empty($region_id)) {
                    $region_model = model('Region');
                    $region_list = $region_model->getList(['region_id' => $region_id], count($region_id), false, 'region_id,region_name');
                    foreach ($region_list['data'] as $v) {
                        $region_arr[$v['region_id']] = $v['region_name'];
                    }
                    unset($region_model,$region_list,$region_id);
                }
            }

            foreach ($list as $v) {
                $address_prefix = '';
                $province = '';
                $city = '';
                $district = '';
                if (isset($v->province_id) && $v->province_id > 0) {
                    $province = isset($region_arr[$v->province_id]) ? $region_arr[$v->province_id] . ' ' : '';
                    $address_prefix .= $province;
                }

                if (isset($v->city_id) && $v->city_id > 0) {
                    $city = isset($region_arr[$v->city_id]) ? $region_arr[$v->city_id] . ' ' : '';
                    $address_prefix .= $city;
                }

                if (isset($v->district_id) && $v->district_id > 0) {
                    $district = isset($region_arr[$v->district_id]) ? $region_arr[$v->district_id] . ' ' : '';
                    $address_prefix .= $district;
                }

                $v->address_prefix = $address_prefix;
                $v->province = $province;
                $v->city = $city;
                $v->district = $district;
            }
        }

        return $list;
    }

    public function getInfo(array $where)
    {
        $info = $this->contract_model->getInfo($where, true, true);

        if (!empty($info)) {
            //处理信息录入人
            $admin_user_model = model('AdminUser');
            if ($info['add_uid'] > 0) {
                $user_info = $admin_user_model->getInfo(['id' => $info['add_uid']], 'username');
                $info['add_user_name'] = isset($user_info->username) ? $user_info->username : '';
            } else {
                $info['add_user_name'] = '';
            }

            //处理业务类型
            if ($info['class'] > 0) {
                $type_info = $this->contract_type_model->getInfo(['id' => $info['class']], true, true);
                $info['class_name'] = isset($type_info['type']) ? $type_info['type'] : '';
            }
            if ($info['type'] > 0) {
                $type_info = $this->contract_type_model->getInfo(['id' => $info['type']]);
                $info['type_name'] = isset($type_info['type']) ? $type_info['type'] : '';
            }

            /*处理项目状态*/
            $status_desc = ContractHelp::contract_status_desc();
            $info['status_desc'] = $status_desc[$info['status']];

            //处理合同生命周期：生命周期顺序：数据录入-> 回收/ 作废
            $life_arr = [];
            if ($info['status'] == CONTRACT_STATUS_DISCARD) {
                $user_info = $admin_user_model->getInfo(['id' => $info['discard_operate_uid']], 'username');

                $life_arr[] = [
                    'time' => date('Y-m-d H:i:s', $info['discard_operate_time']),
                    'title' => '作废操作',
                    'operator' => isset($user_info->username) ? $user_info->username : '',
                    'content' => "作废原因：" . $info['discard_reason'],
                ];
            }

            /*客户信息*/
            if ($info['customer_id'] > 0) {
                $customer_name = $this->customer_model->getInfo(['id' => $info['customer_id']], 'company_name');
                $info['customer_name'] = isset($customer_name['company_name']) ? $customer_name['company_name'] : '';
            } else {
                $info['customer_name'] = '';
            }

            /*检查是否有回收*/
            if ($info['take_back_user']) {
                $user_info = $admin_user_model->getInfo(['id' => $info['take_back_operate_uid']], 'username');
                $life_arr[] = [
                    'time' => date('Y-m-d H:i:s', $info['take_back_operate_time']),
                    'title' => '回收操作',
                    'operator' => isset($user_info->username) ? $user_info->username : '',
                    'content' => '人员【' . $info['take_back_user'] . '】于：' . date('Y-m-d H:i:s', $info['take_back_time']) . ' 回收合同',
                ];
            }

            $info['life_arr'] = $life_arr;

            /*合同扫描件*/
            $info['scanning_file'] = $info['scanning_file'] ? get_file_http_url($info['scanning_file'], true) : '';
        } else {
            $info = [
                'id' => 0,
                'contract_number' => '',
                'year' => '',
                'serial_number' => '',
                'customer_id' => '',
                'customer_name' => '',
                'status' => '',
                'class' => 0,
                'class_name' => '',
                'type' => 0,
                'type_name' => '',
                'service_content' => '',
                'sale_manager' => '',
                'project_name' => '',
                'project_manager' => '',
                'contract_amount' => '',
                'is_include_tax' => '',
                'contract_receiver' => '',
                'take_back_time' => '',
                'take_back_user' => '',
                'take_back_operate_time' => '',
                'take_back_operate_uid' => '',
                'discard_operate_time' => '',
                'discard_operate_uid' => '',
                'discard_reason' => '',
                'is_delete' => '',
                'add_uid' => '',
                'add_user_name' => '',
                'update_time' => '',
                'create_time' => '',
                'life_arr' => [],
                'status_desc' => '',
                'scanning_file' => ''
            ];
        }

        return $info;
    }

    /**
     * (放入回收站)删除一条/多条 客户信息
     * @param array $ids
     * @return bool
     */
    public function deleteData(array $ids)
    {
        if (empty($ids)) {
            return true;
        }

        $data = [
            'is_delete' => STATUS_DELETE,
        ];
        foreach ($ids as $id) {
            $res = $this->contract_model->saveDate($id, $data);
            if ($res === false) {
                return false;
            }
        }

        return true;
    }


    /**
     * 获取所有的业务类型，并处理成 父-子 结构的数组
     * @param bool $need_id_to_data 是否需要id=>data 格式的数据
     * @return array
     */
    public function getAllTontractType($need_id_to_data = false)
    {
        $type_list = $this->contract_type_model->getList([], 1000, false, true, true);

        if ($need_id_to_data) {
            $id_to_data = [];
            foreach ($type_list['data'] as $v) {
                $id_to_data[$v['id']] = $v;
            }
            return [
                'tree_data' => $this->getTree($type_list['data']),
                'id_to_data' => $id_to_data,
            ];
        }
        return $this->getTree($type_list['data']);
    }

    /**
     * 处理业务类型数据为 父子 结构
     * @param array $arr
     * @return array
     */
    private function getTree(array $arr) {
        if (empty($arr)) {
            return [];
        }
        $tree = [];
        foreach ($arr as $k => &$v) {
            if ($v['parent_id'] == 0) {
                $v['son_list'] = [];
                $tree[] = $v;
                unset($arr[$k]);
            }
        }

        foreach ($arr as $v) {
            if ($v['parent_id'] > 0) {
                foreach ($tree as &$v_tree) {
                    if ($v['parent_id'] == $v_tree['id']) {
                        $v_tree['son_list'][] = $v;
                    }
                }
            }
        }

        return $tree;
    }

    /**
     * 回收合同
     * @param $id
     * @param $data
     * @return bool
     */
    public function doRecycle($id, $data)
    {
        if ($id <= 0 || empty($data)) {
            exception('缺少必要的参数！');
        }

        /*检查合同是否存在，且可以被回收*/
        $contract_info = $this->contract_model->getInfo([
            'id' => $id
        ], 'status');
        if (empty($contract_info)) {
            exception('指定合同不存在，或已被删除，请检查！');
        }

        if ($contract_info['status'] == CONTRACT_STATUS_RECYCLE) {
            exception('指定合同已经被回收，请勿重复操作！');
        }

        if ($contract_info['status'] != CONTRACT_STATUS_INIT) {
            exception('指定合同未处于初始状态，无法进行此操作！');
        }

        $res = $this->contract_model->saveDate($id, $data);
        if ($res === false) {
            return false;
        }

        return true;
    }


    /**
     * 作废合同
     * @param $id
     * @param $data
     * @return bool
     */
    public function doDiscard($id, $data)
    {
        if ($id <= 0 || empty($data)) {
            exception('缺少必要的参数！');
        }

        /*检查合同是否存在，且可以被回收*/
        $contract_info = $this->contract_model->getInfo([
            'id' => $id
        ], 'status');
        if (empty($contract_info)) {
            exception('指定合同不存在，或已被删除，请检查！');
        }

        if ($contract_info['status'] == CONTRACT_STATUS_DISCARD) {
            exception('指定合同已经被作废，请勿重复操作！');
        }

        $res = $this->contract_model->saveDate($id, $data);
        if ($res === false) {
            return false;
        }

        return true;
    }

    /**
     * 获取合同签订公司列表
     * @param array $where
     * @return mixed
     */
    public function getSignCompanyList($where = [])
    {
        $list = model('SignCompany')->getList($where, 100, false, true, true);

        return $list['data'];
    }

    /**
     * 获取合同签订公司的code-公司名称 映射
     * @return array
     */
    public function getSignCompanyCodeMap()
    {
        $list = model('SignCompany')->getList([], 100, false, true, true);

        $map = [];
        foreach ($list['data'] as $v) {
            $map[$v['code']] = $v['sign_company'];
        }
        return $map;
    }

    /**
     * 获取当前登录用户可以查看的签订合同的公司 以及后续的搜索条件
     *
     *  情况1-1：个人信息的code为空，并且未指定code，可以查看全部全部，
     *  情况1-2：个人信息的code为空，并且指定了code，查看指定，
     *  情况2-1：个人信息的code不为空，并且未指定code，只能查看自己的code的全部
     *  情况2-2：个人信息的code不为空，并且指定了code，查看指定
     * @param array $user_info
     * @param string $sign_company_code
     * @return array
     */
    public function getSignCompanyListAndCodeWhere(array $user_info, $sign_company_code = '')
    {
        if (empty($user_info)) {
            exception('缺少必要的参数！');
        }

        if ($user_info['id'] == 1 || empty($user_info['code'])) {
            $where_sign_company = [];
        } else {
            $where_sign_company = [
                'code' => $user_info['code'],
            ];
        }

        $sign_company_list = $this->getSignCompanyList($where_sign_company);

        if (empty($user_info['code'])) {
            if (empty($sign_company_code) || !in_array($sign_company_code, array_column($sign_company_list, 'code'))) {
                //情况1-1
                $sign_company_code_where = [];
            } else {
                //情况1-2
                $sign_company_code_where = $sign_company_code;
            }
        } else {
            if (empty($sign_company_code) || !in_array($sign_company_code, array_column($sign_company_list, 'code'))) {
                //情况2-1
                $sign_company_code_where = $user_info['code'];
            } else {
                //情况2-2
                $sign_company_code_where = $sign_company_code;
            }
        }

        return [
            'sign_company_list' => $sign_company_list,
            'sign_company_code_where' => $sign_company_code_where,
        ];
    }

    /**
     * 检查合同是否存在
     * @param $contract_number
     * @return bool
     */
    public function chechkContractIsExists($contract_number)
    {
        if ($this->contract_model->getInfo(['contract_number' => $contract_number], 'contract_number')) {
            return true;
        }
        return false;
    }

    /**
     * 获取合同的简单信息
     * @param array $where
     * @param bool $fields
     * @return mixed
     */
    public function getSimpleInfo(array $where, $fields = true)
    {
        $info = $this->contract_model->getInfo($where, $fields, true);
        return $info;
    }

    /**
     * 删除打包记录
     * @param $id
     * @return bool
     */
    public function deletePackRecord($id)
    {
        if ($id <= 0) {
            return false;
        }

        $download_record_model = model('DownloadRecord');
        $info = $download_record_model->getInfo(['id' => $id]);
        if (empty($info)) {
            return true;
        }
        $file_url = $info->down_url;

        $del_res = $download_record_model->delOneById($id);
        if ($del_res === false) {
            return false;
        }

        if (!empty($file_url)) {
            /*删除对应文件*/
            @unlink(UPLOAD_FILE_PATH . $file_url);
        }

        return true;
    }

    /**
     * 根据条件搜索合同。并打包合同的扫描件
     * @param $project_group_id
     * @param $recycle_begin
     * @param $recycle_end
     * @return array
     */
    public function packContractScanningFiles($project_group_id, $recycle_begin, $recycle_end)
    {
        //打包文件存放规则：UPLOAD_FILE_PATH / package / Ymd / md5(jsoncode($where)).zip

        /*检查是否已经存在了下载记录*/
        $download_record_model = model('DownloadRecord');
        $have_packed = $download_record_model->getInfo([
            'project_group_id'  => $project_group_id,
            'recycle_begin'     => date('Y-m-d', $recycle_begin),
            'recycle_end'       => date('Y-m-d', $recycle_end),
            'status'            => PACK_STATUS_SUCCESS,
        ]);

        if (!empty($have_packed) && !empty($have_packed->down_url)) {
            $down_url = $have_packed->down_url;//已经生成的记录
            $old_file_disk_path = get_disk_url($down_url);
            if (file_exists($old_file_disk_path)) {
                return [
                    'old' => true,
                    'url' => get_file_http_url($down_url),
                ];
            }
        }

        /*重新生成*/
        $where = [
            'project_group_id'  => $project_group_id,
            'start'             => $recycle_begin,
            'end'               => $recycle_end,
        ];
        $list = $this->contract_model->getList($where, 5000, false, 'scanning_file', true);

        if (empty($list['data'])) {
            exception('抱歉，没有找到符合条件的扫描件！');
        }

        $scanning_file_list = array_column($list['data'], 'scanning_file');
        $scanning_file_list = array_unique(array_filter($scanning_file_list));
        if (empty($scanning_file_list)) {
            exception('抱歉，没有找到符合条件的合同扫描件！');
        }

        /*处理成磁盘完整路径*/
        foreach ($scanning_file_list as $k => &$v) {
            $v = get_disk_url($v);
            if (!file_exists($v)) {
                unset($scanning_file_list[$k]);
            }
        }

        if (empty($scanning_file_list)) {
            exception('抱歉，没有找到符合条件的合同扫描件。');
        }

        /*有文件，记录打包记录*/
        $record_data = [
            'project_group_id'  => $project_group_id,
            'recycle_begin'     => date('Y-m-d', $recycle_begin),
            'recycle_end'       => date('Y-m-d', $recycle_end),
            'create_time'       => time(),
        ];

        $file_path = UPLOAD_FILE_PATH . 'package/' . date('Y-m-d') . '/';
        /*创建一个保存的文件名*/
        $save_name = 'G' . $where['project_group_id'] . '-' . date('ymd', $where['start']) . '-' . date('ymd', $where['end']) . '.zip';
        $file_disk_path = $file_path . $save_name;

        if (!file_exists($file_path)) {
            @mkdir($file_path, 0777, true);
        }

        //文件打包
        $zip = new \org\PHPZip();
        $zip->ZipFile($scanning_file_list, $file_disk_path, 2, './');

        /*再次检查*/
        if (file_exists($file_disk_path)) {
            //压缩成功
            $record_data['status'] = PACK_STATUS_SUCCESS;
            $record_data['down_url'] = str_replace(UPLOAD_FILE_PATH, '', $file_disk_path);
        } else {
            //压缩失败
            $record_data['status'] = PACK_STATUS_FAILED;
            $record_data['errmsg'] = '打包失败';
        }

        $record_id = $download_record_model->addData($record_data);
        if (!$record_id) {
            exception('操作记录失败，请重试！');
        }

        return [
            'old' => false,
            'url' => get_file_http_url(str_replace(UPLOAD_FILE_PATH, '', $file_disk_path)),
        ];
    }

    /**
     * 批量导入合同数据
     *
     * @param array $user_info
     * @return mixed
     */
    public function batchImportData(array $user_info)
    {
        if (empty($user_info)) {
            exception('无法获取登录信息，请重新登录后尝试！');
        }

        $upload_logic = logic('Upload');
        /*设置上传根路径*/
        $upload_logic->setUploadPath(UPLOAD_FILE_PATH . '/import_contract/');
        $res = $upload_logic->uploadFile();//成功后，为上传的文件路径，此处一次只能上传一张

        if ($res && is_array($res)) {
            Log::record('文件上传成功：' . $res[0]);
            $import_res = $this->handleOrderExcelDataToTable($res[0], $user_info);
            return $import_res;
        } else {
            exception($upload_logic->getErrorInfo() ? $upload_logic->getErrorInfo() : '导入失败！');
        }
    }

    /**
     * 把Excel 表里面的订单数据导入到数据库中
     *
     * @author mayy
     * @date 2017-9-30
     * @param $file_name
     * @param $user_info
     * @return mixed
     */
    private function handleOrderExcelDataToTable($file_name, $user_info)
    {
        $header_fields_realtion = ContractHelp::contractDataExcelHeader();
        $excel_data = $this->getDataFromExcel($file_name, $header_fields_realtion, true, false);
        $excel_header_data = $excel_data['header'];
        $excel_data = $excel_data['data'];
        if (empty($excel_data)) {
            exception('文件内容为空！');
        }

        $upload_success_time = date('Y-m-d H:i:s');

        //过滤掉空白行，行内所有字段数据都为空，则认为是空白行
        foreach ($excel_data as $k => &$v) {
            $is_empty_row = true;
            foreach ($v as $v_field) {
                if (!empty($v_field)) {
                    $is_empty_row = false;
                    break;
                }
            }
            if ($is_empty_row) {
                unset($excel_data[$k]);
            }
        }

        if (empty($excel_data)) {
            exception('文件内容为空！');
        }

        //excel字段检查
        $check_excel_fields = $this->checkOrderDataExcelFilds($excel_header_data);
        if (!$check_excel_fields) {
            exception('请按照模板文件格式上传excel文件，确保表头未被修改！');
        }

        $failed_contract_list = [];


        //分别取出业务类型 、业务类型（子） 、 项目组、客户编号 的信息用于查询
        /*业务类型*/
        $class_type_tree = $this->getAllTontractType();

        /*项目组*/
        $project_group_list = logic('Config')->getProjectGroupListReversal();

        /*客户签订公司*/
        $sign_company_map = $this->getSignCompanyCodeMap();

        /*客户编号*/
        $customer_number_id_map = [];
        $customer_number_arr =array_column($excel_data, 'customer_number');
        $customer_number_list = array_filter(array_unique($customer_number_arr));
        $customer_search_list = model('Customer')->getList([
            'customer_number_arr' => $customer_number_list,
        ], count($customer_number_list), false, 'id,customer_number', true);

        foreach ($customer_search_list['data'] as $v_1) {
            $customer_number_id_map[$v_1['customer_number']] = $v_1['id'];
        }
        //TODO $excel_data 异常

        $success_counts = 0;
        foreach ($excel_data as $k => &$v) {
            /*合同签订公司*/
            if (empty($v['sign_company_code'])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '合同签订公司为空',
                ];
                continue;
            }

            $v['sign_company_code'] = strtoupper($v['sign_company_code']);

            if (!isset($sign_company_map[$v['sign_company_code']])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '合同签订公司无法在配置库中找到',
                ];
                continue;
            }
            $sign_company_code = $v['sign_company_code'];

            /*年度*/
            if (empty($v['year'])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '合同年度为空',
                ];
                continue;
            }
            if (!preg_match('/2\d{3}/', $v['year'])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '合同年度数据('.$v['year'].')格式错误，正确格式示例：2018',
                ];
                continue;
            }
            $year = $v['year'];

            /*客户id*/
            if (empty($v['customer_number'])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '客户编号为空',
                ];
                continue;
            }
            if (empty($customer_number_id_map[$v['customer_number']])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '客户编号（'.$v['customer_number'].'）无法在客户库中找到',
                ];
                continue;
            }
            $customer_id = $customer_number_id_map[$v['customer_number']];

            /*营销经理 和 领取人不能为空*/
            if (empty($v['sale_manager']) || empty($v['contract_receiver'])) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '营销经理或合同领取人信息缺失',
                ];
                continue;
            }

            /*业务类型*/
            $class = $type = 0;
            $type_arr = [];
            if (!empty($v['class'])) {
                foreach ($class_type_tree as $v_class) {
                    if ($v['class'] == $v_class['type']) {
                        $class = $v_class['id'];
                        $type_arr = $v_class['son_list'];
                    }
                }

                if (!empty($v['type']) && !empty($type_arr)) {
                    $flag_type = false;
                    foreach ($type_arr as $v_type) {
                        if ($v['type'] == $v_type['type']) {
                            $type = $v_type['id'];

                        }
                    }
                }
            }

            /*项目组*/
            $project_group_id = isset($project_group_list[$v['project_group']]) ? $project_group_list[$v['project_group']] : 0;

            /*格式化合同金额*/
            $contract_amount = is_numeric($v['contract_amount']) ? number_format($v['contract_amount'],2,".","") : 0.00;

            //数据处理成可以入库的结构
            $contract_number_info = $this->getContractNumber($sign_company_code, $year);
            $customer_data = [
                'contract_number' => $contract_number_info['contract_number'],
                'sign_company_code' => $sign_company_code,
                'year' => $year,
                'serial_number' => $contract_number_info['serial_number'],
                'customer_id' => $customer_id,
                'status' => CONTRACT_STATUS_INIT,
                'class' => $class,
                'type' => $type,
                'project_group_id' => $project_group_id,
                'service_content' => $v['service_content'],
                'sale_manager' => $v['sale_manager'],
                'project_name' => $v['project_name'],
                'project_manager' => $v['project_manager'],
                'contract_amount' => $contract_amount,
                'is_include_tax' => in_array($v['is_include_tax'], ['0','否','不','不含']) ? 0 : 1,
                'contract_receiver' => $v['contract_receiver'],
                'add_uid' => $user_info['id'],
                'create_time' => time(),
            ];

            $res = $this->contract_model->addData($customer_data);
            if (!$res) {
                $failed_contract_list[] = [
                    'row' => $k,
                    'reason' => '插入数据库失败（可重试）',
                ];
                continue;
            } else {
                $success_counts++;
            }
        }

        return [
            'total_counts' => count($excel_data),
            'success_counts' => $success_counts,
            'failed_contract_list' => $failed_contract_list,
            'upload_complete_time' => $upload_success_time,
        ];
    }

    /**
     * 从文件中取出数据
     * @param $file_name
     * @param array $field_name_map
     * @param bool $need_header
     * @param bool $only_header
     * @return array
     */
    private function getDataFromExcel($file_name, array $field_name_map = [], $need_header = true, $only_header = false)
    {
        if (!file_exists($file_name)) {
            exception('文件不存在！');
        }
        vendor("PHPExcel.PHPExcel");

        //get ext of file
        $tmp_arr = explode('.', $file_name);
        $exts = $tmp_arr[count($tmp_arr) - 1];

        $objReader = null;
        if ($exts == 'xls') {
            $objReader = new \PHPExcel_Reader_Excel5();
        } else if ($exts == 'xlsx') {
            $objReader = new \PHPExcel_Reader_Excel2007();
        } else {
            exception("Error excel file");
        }

        //read data
        $PHPExcel       = $objReader->load($file_name);
        $currentSheet   = $PHPExcel->getSheet(0);
        $allColumn      = $currentSheet->getHighestColumn();
        $allRow         = $currentSheet->getHighestRow();

        //解决 列超出 Z
        ++$allColumn;

        $header = [];
        if ($need_header) {
            /*使用 != 进行判断， 解决 列超出 Z 的问题 */
            for ($currentColumn_header = 'A'; $currentColumn_header != $allColumn; $currentColumn_header++) {
                //location of one data
                $address_header = $currentColumn_header . 1;
                //save to array
                $header[] = trim((string)$currentSheet->getCell($address_header)->getValue());
            }
        }

        $data = [];
        for ($currentRow =2; $currentRow <= $allRow; $currentRow++) {
            for ($currentColumn = 'A'; $currentColumn != $allColumn; $currentColumn++) {
                if (!isset($field_name_map[$currentColumn])) {
                    /*过滤掉未设置映射的列*/
                    continue;
                }
                //location of one data
                $address = $currentColumn . $currentRow;
                //save to array
                $data[$currentRow-1][$field_name_map[$currentColumn]] = trim((string)$currentSheet->getCell($address)->getValue());
            }
        }

        if ($only_header) {
            return $header;
        }

        return [
            'header' => $header,
            'data' => $data
        ];
    }

    /**
     * 检查订单数据excel 的表头是否合法
     * @param array $execl_header
     * @return bool
     */
    private function checkOrderDataExcelFilds(array $execl_header)
    {
        $data_template = ROOT_PATH . '/public/excel_template/contract-list-template.xlsx';

        if (!file_exists($data_template)) {
            exception('模板文件不存在，请联系工程师处理！');
        }

        $template_header = $this->getDataFromExcel($data_template, [], true, true);
        if (empty($template_header)) {
            exception('模板文件内容为空！');
        }
        $template_header = array_filter($template_header);
        $execl_header = array_filter($execl_header);

        if (http_build_query($template_header) != http_build_query($execl_header)) {
            return false;
        }

        return true;
    }

    /**
     * 为导出excel获取合同数据
     * @param array $where
     * @param array $user_info
     * @param  $limit
     * @return array
     */
    public function getListForExport(array $where, array $user_info, $limit)
    {
        $return = [];
        $list = $this->contract_customer_view_model->getList($where, $limit, false, 'id', true);

        if (empty($list['data'])) {
            return $return;
        }

        $ids = array_column($list['data'], 'id');
        if (empty($ids)) {
            return $return;
        }

        $contract_list = $this->contract_model->getList([
            'id' => $ids,
        ], count($ids), false, true, true);
        $return = $contract_list['data'];
        if (empty($return)) {
            return $return;
        }

        $customer_id_name_map = $this->customer_model->getCustomerIdNameMap(array_column($return, 'customer_id'));
        $contract_status_arr = ContractHelp::contract_status_desc();
        foreach ($return as &$v) {
            $v['customer_name'] = empty($customer_id_name_map[$v['customer_id']]['company_name']) ?'' : $customer_id_name_map[$v['customer_id']]['company_name'];
            $v['customer_number'] = empty($customer_id_name_map[$v['customer_id']]['customer_number']) ?'' : $customer_id_name_map[$v['customer_id']]['customer_number'];
            $v['status_desc'] = empty($contract_status_arr[$v['status']]) ? '' : $contract_status_arr[$v['status']];
        }
        return $return;
    }
}